home *** CD-ROM | disk | FTP | other *** search
- Path: xanth!mcnc!rutgers!tut.cis.ohio-state.edu!cwjcc!hal!ncoast!allbery
- From: alex@umbc3.UUCP (Alex S. Crain)
- Newsgroups: comp.sources.misc
- Subject: v04i126: 680x0 COFF disassembler (2 of 2)
- Message-ID: <8810102104.AA05934@umbc3.UMD.EDU>
- Date: 14 Oct 88 23:39:52 GMT
- Sender: allbery@ncoast.UUCP
- Reply-To: alex@umbc3.UUCP (Alex S. Crain)
- Lines: 2299
- Approved: allbery@ncoast.UUCP
-
- Posting-number: Volume 4, Issue 126
- Submitted-by: "Alex S. Crain" <alex@umbc3.UUCP>
- Archive-name: 68kdisasm/Part2
-
- This is part 2 of the dissassembler.
-
- :alex.
- Systems Programmer
- nerwin!alex@umbc3.umd.edu UMBC
- alex@umbc3.umd.edu
-
- #!/bin/sh
- # shar: Shell Archiver (v1.22)
- #
- # Run the following text with /bin/sh to create:
- # Makefile
- # README.FIRST
- # README.orig
- # README.unixpc
- # alloc.c
- # conv.c
- # doc.nr
- # file.c
- # heur.c
- # main.c
- # prin.c
- # unc.h
- #
- sed 's/^X//' << 'SHAR_EOF' > Makefile &&
- XCFLAGS=-O
- XLDFLAGS=-s
- XOBJS=alloc.o file.o libmtch.o robj.o iset.o prin.o heur.o main.o conv.o
- XSHAREDLIB=/lib/shlib.ifile /lib/crt0s.o
- X
- Xdis: $(OBJS)
- X $(LD) $(LDFLAGS) -o dis $(OBJS) $(SHAREDLIB) -lld
- X
- X$(OBJS): unc.h
- SHAR_EOF
- chmod 0644 Makefile || echo "restore of Makefile fails"
- sed 's/^X//' << 'SHAR_EOF' > README.FIRST &&
- X WARNING * WARNING * WARNING * WARNING * WARNING * WARNING * WARNING * WARNING
- X
- X The AT&T licence agreement specifically prohibits the dissassembly
- X of propritory AT&T software. Be aware that use of this program on system
- X software is in clear violation of that agreement. The author(s) of this
- X software in no way incourage its use in any way shape or form for any reason
- X whatsoever, and will not be held liable for anything ever if we can help it.
- X
- X WARNING * WARNING * WARNING * WARNING * WARNING * WARNING * WARNING * WARNING
- SHAR_EOF
- chmod 0644 README.FIRST || echo "restore of README.FIRST fails"
- sed 's/^X//' << 'SHAR_EOF' > README.orig &&
- XI have gotten many many requests to email this or post it, because of
- Xits size email'ing it screws up most mailers, so i am submitting it to
- Xmod.sources to be posted. Please note a major cavaet with this, it was
- Xwritten under Unisoft's port of Unix so the a.out file that it uses
- Xmore closely resembles the b.out.h file that most cross assemblers
- X(e.g. greenhills) use. For the obvious reasons i have not included that
- Xfile with the posting. I did not write this nor do i make any claim to
- Xthat effect.
- X
- X turner@imagen.UUCP <talcott!topaz!Shasta!imagen!Jim.Turner>
- X
- X----------------------------
- XThis is the 68000 disassembler mentioned on the net.
- XIt is not my final version by any means, but I have found it extremely
- Xuseful and it represents several weeks' work.
- X
- X John Collins. <jmc@inset.UUCP>
- SHAR_EOF
- chmod 0644 README.orig || echo "restore of README.orig fails"
- sed 's/^X//' << 'SHAR_EOF' > README.unixpc &&
- X***** README *****
- X
- XThis README superceeds all other README's.
- X
- XProgram History:
- X This started out as the unc program, by John Collins. At that
- Xtime it was a 68000 assembler for the UNISOFT unix environment. It was
- Xposted to the net as a dissasembler for Suns, I don't know who
- Xmodified it for the sun environment or if that was ever done, but
- XJanet Walz taught it about COFF, using the existing assembly syntax, I
- Xreworked the syntax to match the SGS syntax used by the unixpc (and
- Xthe HP9000, I believe). Surprisingly, the code has remained resonably
- Xcoherent during this time, and has remained well structured.
- X
- X
- XCurrent Status:
- X At best, dissassemblers are of dubious value to anyone but system
- Xhackers and compiler writers. As I am both, I expect that this tool will
- Xget used a great deal on *my* machine.
- X
- X The following features are supported
- X 1) symbol resolution is done whenever possible. addresses abouve
- X0x300000 are considered constants (on a unix-pc, ths shared libraries are
- Xmapped in the address space above 0x300000)
- X 2) the dissassembler will attempt to convert pc relative addresses
- Xto label jumps, in that it will calculate the destination address and insert
- Xa label at that point, if one is not already present.
- X 3) the dissassembler decodes jump tables by recognising the swbeg
- Xpsuedo instuction and treating the table as a list of offsets relative
- Xto the start of the table. Again, label insertion is done where neccessary.
- X
- XTHe idea is that you should be able to do
- X
- X % dis foo > foo.s
- X % as foo.s
- X % ld foo.o
- X
- XThis is never completely possible, but it will work on some things. Remember
- Xthat code originally linked to the shared libraries must be loaded with
- X/lib/shlib.ifile. dis output will need a _start symbol inserted at the top
- Xof the output file, as in:
- X
- X text
- X global _start # insert this
- X_start: # and this
- X ...
- X ...
- X
- XAlso note that the assembly output will already contain any necessary
- Xlibrary routines, so linking to libraries will not be neccessary.
- X
- XBUGS:
- X THere are certainly bugs present, and I while I offer no support,
- XI will gladly accept bug reports and publish fixes as I have time. Send
- Xbug reports to:
- X
- X alex@umbc3.ume.edu
- X uunet!umbc3!nerwin!alex
- X
- X Alex Crain
- X
- X
- SHAR_EOF
- chmod 0644 README.unixpc || echo "restore of README.unixpc fails"
- sed 's/^X//' << 'SHAR_EOF' > alloc.c &&
- X/*
- X * SCCS: @(#)alloc.c 1.2 11/2/84 14:17:20
- X * Allocate space etc.
- X *
- X ***********************************************************************
- X * This software is copyright of
- X *
- X * John M Collins
- X * 47 Cedarwood Drive
- X * St Albans
- X * Herts, AL4 0DN
- X * England +44 727 57267
- X *
- X * and is released into the public domain on the following conditions:
- X *
- X * 1. No free maintenance will be guaranteed.
- X * 2. Nothing may be based on this software without
- X * acknowledgement, including incorporation of this
- X * notice.
- X *
- X * Notwithstanding the above, the author welcomes correspondence and bug
- X * fixes.
- X ***********************************************************************
- X */
- X
- X#include <stdio.h>
- X#include <a.out.h>
- X#include <setjmp.h>
- X#include <ldfcn.h>
- X#include "unc.h"
- X
- X#define STINC 10
- X
- Xchar *malloc(), *realloc();
- Xchar *strncpy();
- Xvoid gette(), getde(), setde(), putte(), putde();
- Xvoid unimpl();
- Xlong gettw();
- X
- Xef_fids mainfile;
- X
- X/*
- X * Oops! out of memory.....
- X */
- X
- Xvoid nomem()
- X{
- X (void) fprintf(stderr, "Sorry - run out of memory\n");
- X exit(255);
- X}
- X
- X/*
- X * Look up hash value of symbol.
- X */
- X
- Xunsigned shash(str)
- Xregister char *str;
- X{
- X register unsigned result = 0;
- X register int cnt = 0;
- X
- X while (*str && cnt < MAXCHARS) {
- X result += *str++;
- X cnt++;
- X }
- X return result % HASHMOD;
- X}
- X
- X/*
- X * Look up hash value of symbol, possibly allocating a new symbol.
- X */
- X
- Xsymbol lookup(str)
- Xchar *str;
- X{
- X register symbol res, *pp;
- X register int len;
- X
- X pp = &symbhash[shash(str)];
- X res = *pp;
- X while (res != NULL) {
- X if (strncmp(res->s_name, str, MAXCHARS) == 0)
- X return res;
- X pp = &res->s_next;
- X res = *pp;
- X }
- X for (len = 0; len < MAXCHARS; len++)
- X if (str[len] == '\0')
- X break;
- X len++;
- X res = (symbol) malloc(sizeof(struct symstr) + len);
- X if (res == NULL)
- X nomem();
- X *pp = res;
- X res->s_next = NULL;
- X (void) strncpy(res->s_name, str, len);
- X res->s_name[len] = '\0'; /* Null-terminate */
- X res->s_newsym = 1;
- X res->s_glob = 0;
- X res->s_invent = 0;
- X res->s_link = NULL;
- X res->s_used = 0;
- X res->s_defs = 0;
- X res->s_lsymb = 0;
- X return res;
- X}
- X
- X/*
- X * Invent a symbol, making sure that we don't know it.
- X */
- X
- Xsymbol inventsymb(prefix)
- Xchar *prefix;
- X{
- X static int nsymb = 0;
- X char schars[10];
- X register symbol res;
- X
- X do (void) sprintf(schars, "%s%d", prefix, ++nsymb);
- X while (!(res = lookup(schars))->s_newsym);
- X
- X res->s_newsym = 0;
- X res->s_invent = 1;
- X return res;
- X}
- X
- X/*
- X * Reallocate symbol table.
- X */
- X
- Xvoid reallst(outf)
- Xregister ef_fid outf;
- X{
- X outf->ef_stmax += STINC;
- X if (outf->ef_stvec == NULL)
- X outf->ef_stvec = (symbol *) malloc(outf->ef_stmax * sizeof(symbol));
- X else
- X outf->ef_stvec = (symbol *) realloc(outf->ef_stvec,
- X outf->ef_stmax * sizeof(symbol));
- X if (outf->ef_stvec == NULL)
- X nomem();
- X}
- X
- X/*
- X * Search through existing symbol table for symbol with given
- X * value. Invent a new one if needed.
- X */
- X
- Xsymbol getnsymb(fid, seg, pos)
- Xregister ef_fid fid;
- Xunsigned seg;
- Xlong pos;
- X{
- X register int i;
- X register symbol res;
- X
- X /*********** MACHINE DEPENDENT ******************************
- X * Convert relocation segment type (argument) to symbol type
- X * (as remembered in symbol table). Don't ask me why they
- X * have to be different.....
- X */
- X
- X /*
- X * See if the reference is to an external symbol.
- X * If so, use that.
- X */
- X
- X for (i = 0; i < fid->ef_stcnt; i++) {
- X res = fid->ef_stvec[i];
- X if (res->s_type == seg && res->s_value == pos)
- X return res;
- X }
- X
- X /*
- X * Invent a symbol and use that.
- X */
- X
- X res = inventsymb("RS");
- X if (fid->ef_stcnt >= fid->ef_stmax)
- X reallst(fid);
- X fid->ef_stvec[fid->ef_stcnt++] = res;
- X res->s_type = seg;
- X res->s_value = pos;
- X if (seg == S_TEXT) {
- X t_entry tent;
- X gette(fid, pos, &tent);
- X tent.t_bdest = 1;
- X tent.t_lab = res;
- X putte(fid, pos, &tent);
- X }
- X else if (seg == S_DATA || seg == S_BSS) {
- X d_entry dent;
- X getde(fid, pos, &dent);
- X dent.d_lab = res;
- X putde(fid, pos, &dent);
- X }
- X
- X return res;
- X}
- X
- X/*
- X * Assuming address given is in text segment, find its label, or invent
- X * one. Also set where refered from.
- X */
- X
- Xsymbol textlab(loc, refpos)
- Xlong loc, refpos;
- X{
- X t_entry tent;
- X
- X gette(&mainfile, loc, &tent);
- X if (tent.t_type == T_CONT)
- X return NULL;
- X if (tent.t_lab == NULL) {
- X tent.t_lab = inventsymb("TS");
- X tent.t_lab->s_type = S_TEXT;
- X tent.t_lab->s_value = loc;
- X tent.t_bdest = 1;
- X putte(&mainfile, loc, &tent);
- X }
- X else
- X tent.t_lab->s_used++;
- X if (tent.t_refhi < refpos) {
- X tent.t_refhi = refpos;
- X putte(&mainfile, loc, &tent);
- X }
- X if (tent.t_reflo > refpos) {
- X tent.t_reflo = refpos;
- X putte(&mainfile, loc, &tent);
- X }
- X return tent.t_lab;
- X}
- X
- X/*
- X * Note references to data.
- X */
- X
- Xvoid mkdref(tpos, size)
- Xlong tpos;
- Xunsigned size;
- X{
- X t_entry tent;
- X d_entry dent;
- X register symbol ds;
- X int dchng = 0;
- X int wsize;
- X long dpos;
- X
- X gette(&mainfile, tpos, &tent);
- X if (tent.t_relsymb != NULL)
- X return;
- X
- X dpos = gettw(&mainfile, tpos, R_LONG);
- X if (dpos < mainfile.ef_dbase || dpos > mainfile.ef_end)
- X return;
- X
- X switch (size) {
- X default:
- X wsize = D_BYTE;
- X break;
- X case 2:
- X wsize = D_WORD;
- X break;
- X case 4:
- X wsize = D_LONG;
- X break;
- X }
- X
- X getde(&mainfile, dpos, &dent);
- X if ((ds = dent.d_lab) == NULL) {
- X if (dpos >= mainfile.ef_bbase) {
- X ds = inventsymb("BS");
- X ds->s_type = S_BSS;
- X }
- X else {
- X ds = inventsymb("DS");
- X ds->s_type = S_DATA;
- X }
- X ds->s_value = dpos;
- X dent.d_lab = ds;
- X dchng++;
- X }
- X else
- X ds->s_used++;
- X
- X if (dent.d_type != D_BYTE) {
- X if (dent.d_type != wsize) {
- X if (dent.d_type == D_ADDR) {
- X if (wsize != D_LONG)
- X unimpl("Addr word usage");
- X }
- X else if (dent.d_type > wsize) {
- X dchng++;
- X dent.d_type = wsize;
- X dent.d_lng = size;
- X }
- X }
- X }
- X else {
- X dent.d_type = wsize;
- X dent.d_lng = size;
- X dchng++;
- X }
- X if (dchng) {
- X putde(&mainfile, dpos, &dent);
- X for (dchng = 1; dchng < size; dchng++)
- X setde(&mainfile, dpos+dchng, D_CONT, 1);
- X }
- X
- X tent.t_relsymb = ds;
- X putte(&mainfile, tpos, &tent);
- X}
- X
- X/*
- X * Add item to common or abs list.
- X */
- X
- X#define COMINC 10
- X
- Xvoid addit(cp, symb)
- Xregister struct commit *cp;
- Xsymbol symb;
- X{
- X if (cp->c_int >= cp->c_max) {
- X cp->c_max += COMINC;
- X if (cp->c_symb == NULL)
- X cp->c_symb = (symbol *) malloc(COMINC*sizeof(symbol));
- X else
- X cp->c_symb = (symbol *)
- X realloc(cp->c_symb,
- X cp->c_max * sizeof(symbol));
- X if (cp->c_symb == NULL)
- X nomem();
- X }
- X cp->c_symb[cp->c_int++] = symb;
- X}
- SHAR_EOF
- chmod 0644 alloc.c || echo "restore of alloc.c fails"
- sed 's/^X//' << 'SHAR_EOF' > conv.c &&
- X#include <stdio.h>
- X#include <a.out.h>
- X#include <ldfcn.h>
- X#include "unc.h"
- X
- Xunsigned convtosun(sym)
- Xstruct syment *sym;
- X{
- X unsigned suntype;
- X
- X /* everything in shlib is an external constant */
- X if (sym->n_value >= 0x300000) {
- X sym->n_scnum = N_ABS;
- X sym->n_sclass = C_EXT;
- X }
- X switch(sym->n_scnum) {
- X case N_UNDEF:
- X case N_DEBUG: /* call things that don't map well "undefined" */
- X case N_TV:
- X case P_TV:
- X suntype = S_UNDF;
- X break;
- X case N_ABS:
- X suntype = S_ABS;
- X break;
- X case 1:
- X suntype = S_TEXT;
- X break;
- X case 2:
- X suntype = S_DATA;
- X break;
- X case 3:
- X suntype = S_BSS;
- X break;
- X }
- X
- X if (sym->n_sclass == C_EXT)
- X suntype = suntype | S_EXT;
- X
- X return(suntype);
- X}
- SHAR_EOF
- chmod 0644 conv.c || echo "restore of conv.c fails"
- sed 's/^X//' << 'SHAR_EOF' > doc.nr &&
- X.\"/*% nroff -cm -rL72 %|epson|spr -f plain.a -h uncdoc -w
- X.nr Hb 7
- X.nr Hs 3
- X.ds HF 3 3 3 3 3 3 3
- X.nr Hu 5
- X.nr Hc 1
- X.SA 1
- X.PH "''A Disassembler''"
- X.PF "'Issue %I%'- Page \\\\nP -'%G%'"
- X.H 1 "Introduction"
- XThis document describes the first release of a disassembler for UNIX
- Xexecutable files.
- XThe key features are:
- X.AL
- X.LI
- XFor object files the output can be assembled to generate the same
- Xobject module, (apart from minor variations in symbol table ordering) as the
- Xinput.
- X.LI
- XFor stripped executable files object modules and libraries may be scanned,
- Xmodules in the main input identified and the appropriate names automatically
- Xinserted into the output.
- X.LI
- XAn option is available to convert most non-global names into local symbols,
- Xwhich cuts down the symbols in the generated assembler file.
- X.LI
- XThe disassembler copes reasonably with modules merged with the
- X.B "-r"
- Xoption to
- X.B "ld" ,
- Xgenerating a warning message as to the number of modules involved.
- X.LE
- X.P
- XAt present this is available for certain Motorola 68000 ports of UNIX
- XSystem III and System V. Dependencies on
- X.AL a
- X.LI
- XInstruction set.
- X.LI
- XObject module format.
- X.LI
- XLibrary module format.
- X.LI
- XAssembler output format.
- X.LE
- X.P
- Xare hopefully sufficiently localised to make the product useful as a
- Xbasis for other disassemblers for other versions of UNIX.
- X.P
- XThe product is thus distributed in source form at present.
- X.H 1 "Use"
- XThe disassembler is run by entering:
- X.DS I
- Xunc mainfile lib1 lib2 ...
- X.DE
- X.P
- XThe first named file is the file to be disassembled, which should be
- Xa single file, either an object module, a (possibly stripped) executable
- Xfile, or a library member. Library members are designated using a
- Xparenthesis notation, thus:
- X.DS I
- Xunc '/lib/libc.a(printf.o)'
- X.DE
- X.P
- XIt is usually necessary to escape the arguments in this case to prevent
- Xmisinterpretation by the shell. Libraries in standard places such as
- X.I "/lib"
- Xand
- X.I "/usr/lib"
- Xmay be specified in the same way as to
- X.B "ld" ,
- Xthus
- X.DS I
- Xunc '-lc(printf.o)'
- Xunc '-lcurses(wmove.o)'
- X.DE
- X.P
- XAs an additional facility, the list of directories searched for
- Xlibraries may be varied by setting the environment variable
- X.B "LDPATH" ,
- Xwhich is interpreted similarly to the shell
- X.B "PATH"
- Xvariable, and of course defaults to
- X.DS I
- XLDPATH=/lib:/usr/lib
- X.DE
- X.P
- XAs a further facility, the insertion of
- X.B "lib"
- Xbefore and
- X.B ".a"
- Xafter the argument may be suppressed by using a capital
- X.B "-L"
- Xargument, thus to print out the assembler for
- X.I "/lib/crt0.o" ,
- Xthen the command
- X.DS I
- Xunc -Lcrt0.o
- X.DE
- X.P
- Xshould have the desired effect.
- X.P
- XSecond and subsequent file arguments are only referenced for stripped
- Xexecutable files, and may consist of single object files and library
- Xmembers, using the same syntax as before, or whole libraries of object
- Xfiles, thus:
- X.DS I
- Xunc strippedfile -Lcrt0.o -lcurses -ltermcap '-lm(sqrt.o)' -lc
- X.DE
- X.P
- XIt is advisable to make some effort to put the libraries to be searched
- Xin the order in which they were originally loaded. This is because the
- Xsearch for each module starts where the previously matched module ended.
- XHowever, no harm is done if this rule is not adhered to apart from
- Xincreased execution time except in the rare cases where the disassembler
- Xis confused by object modules which are very nearly similar.
- X.H 1 "Additional options"
- XThe following options are available to modify the behaviour of the
- Xdisassembler.
- X.VL 15 2
- X.LI "-o file"
- XCauses output to be sent to the specified file instead of the standard
- Xoutput.
- X.LI "-t prefix"
- XCauses temporary files to be created with the given prefix. The default
- Xprefix is
- X.B "split" ,
- Xthus causing two temporary files to be created with this prefix in the
- Xcurrent directory. If it is desired, for example, to create the files as
- X.B "/tmp/xx*" ,
- Xthen the argument
- X.B "-t /tmp/xx"
- Xshould be given. Note that the temporary files may be very large as a
- Xcomplete map of the text and data segments is generated.
- X.LI "-a"
- XSuppresses the generation of non-global absolute symbols from the
- Xoutput. This saves output from C compilations without any obvious
- Xproblems, but the symbols are by default included in the name of
- Xproducing as nearly identical output as possible to the original source.
- X.LI "-s"
- XCauses an additional scan to take place where all possible labels are
- Xreplaced by local symbols. The local symbols are inserted in strictly
- Xascending order, starting at 1.
- X.LI "-v"
- XCauses a blow-by-blow account of activities to be output on the standard
- Xerror.
- X.LI "-V"
- XCauses shlib symbol values to be printed at the top of the output, if they
- Xexist in the symbol table. normally these are ommited because they are constant
- Xvalues derived form the file /lib/shlib.ifile
- X.LE
- X.H 1 "Diagnostics etc"
- XTruncated or garbled object and library files usually cause processing
- Xto stop with an explanatory message.
- X.P
- XThe only other kinds of message are some passing warnings concerning
- Xobscure constructs not handled, such as the relocation of byte fields,
- Xor the relocation of overlapping fields. Occasionally a message
- X.DS I
- XLibrary clash: message
- X.DE
- X.P
- Xmay appear and processing cease. This message is found where at a late
- Xstage in processing libraries, the program discovers that due to the
- Xextreme similarity of two or more library members, it has come to the
- Xwrong conclusion about which one to use. The remedy here is to spell out
- Xto the program which members to take in which order.
- X.H 1 "Future development"
- XIn the future it is hoped to devise ways of making the disassembler
- Xindependent of all the above-mentioned version dependencies, by first
- Xreading a files defining these things. This will probably be applied
- Xafter the Common Object Format becomes more standard.
- X.P
- XIn the long term it would be desirable and useful to enhance the product
- Xto produce compilable C in addition to assemblable assembler. Stages in
- Xthe process are seen as follows:
- X.AL
- X.LI
- XBetter identification of basic blocks in the code. Switch statements are
- Xa major problem here, as are constant data held in the text segment.
- X.LI
- XMarrying of data to the corresponding text. It is in various places hard
- Xto divorce static references "on the fly" (e.g. strings, and switch
- Xlists in some implementations) from static at the head of a module. This
- Xis part of the problem of identifying basic blocks.
- X.LI
- XCompilation of header files to work out structure references within the
- Xtext. At this stage some interaction may be needed.
- X.LE
- X.P
- XMeanwhile the product is one which is a useful tool to the author in its
- Xpresent form. Comments and suggestions as to the most practical method
- Xof improving the product in the ways suggested or in other ways would be
- Xgratefully considered.
- SHAR_EOF
- chmod 0644 doc.nr || echo "restore of doc.nr fails"
- sed 's/^X//' << 'SHAR_EOF' > file.c &&
- X/*
- X * SCCS: @(#)file.c 1.2 11/2/84 14:17:35
- X * Various operations on files.
- X *
- X ***********************************************************************
- X * This software is copyright of
- X *
- X * John M Collins
- X * 47 Cedarwood Drive
- X * St Albans
- X * Herts, AL4 0DN
- X * England +44 727 57267
- X *
- X * and is released into the public domain on the following conditions:
- X *
- X * 1. No free maintenance will be guaranteed.
- X * 2. Nothing may be based on this software without
- X * acknowledgement, including incorporation of this
- X * notice.
- X *
- X * Notwithstanding the above, the author welcomes correspondence and bug
- X * fixes.
- X ***********************************************************************
- X */
- X
- X#include <stdio.h>
- X#include <a.out.h>
- X#include <ldfcn.h>
- X#include "unc.h"
- X
- Xlong lseek();
- Xvoid unimpl();
- X
- X/*
- X * Validate addr and get text entry corresponding to it from the given
- X * file.
- X */
- X
- Xvoid gette(fid, addr, te)
- Xregister ef_fid fid;
- Xregister long addr;
- Xt_entry *te;
- X{
- X addr -= fid->ef_tbase;
- X if (addr < 0x300000 &&
- X (addr < 0 || addr > fid->ef_tsize || (addr & 1) != 0))
- X {
- X (void) fprintf(stderr, "Invalid text address %lx\n", addr);
- X exit(200);
- X }
- X (void) lseek(fid->ef_t, (long)(addr * sizeof(t_entry)/2), 0);
- X if (read(fid->ef_t, (char *) te, sizeof(t_entry)) != sizeof(t_entry)) {
- X (void) fprintf(stderr, "Trouble reading text at %lx\n", addr);
- X exit(201);
- X }
- X}
- X
- X/*
- X * Store a text entry.
- X */
- X
- Xvoid putte(fid, addr, te)
- Xregister ef_fid fid;
- Xregister long addr;
- Xt_entry *te;
- X{
- X addr -= fid->ef_tbase;
- X if (addr < 0x300000 &&
- X (addr < 0 || addr > fid->ef_tsize || (addr & 1) != 0))
- X {
- X (void) fprintf(stderr, "Invalid text address %lx\n", addr);
- X exit(200);
- X }
- X (void) lseek(fid->ef_t, (long)(addr * sizeof(t_entry)/2), 0);
- X (void) write(fid->ef_t, (char *) te, sizeof(t_entry));
- X}
- X
- X/*
- X * Validate addr and get data entry corresponding to it from the given
- X * file.
- X */
- X
- Xvoid getde(fid, addr, de)
- Xregister ef_fid fid;
- Xregister long addr;
- Xd_entry *de;
- X{
- X if (addr < 0x300000 && (addr < fid->ef_dbase || addr > fid->ef_end))
- X {
- X (void) fprintf(stderr, "Invalid data address %lx\n", addr);
- X exit(200);
- X }
- X addr -= fid->ef_dbase;
- X (void) lseek(fid->ef_d, (long)(addr * sizeof(d_entry)), 0);
- X if (read(fid->ef_d, (char *) de, sizeof(d_entry)) != sizeof(d_entry)) {
- X (void) fprintf(stderr, "Trouble reading data at %lx\n", addr);
- X exit(201);
- X }
- X}
- X
- X/*
- X * Store a data entry.
- X */
- X
- Xvoid putde(fid, addr, de)
- Xregister ef_fid fid;
- Xregister long addr;
- Xd_entry *de;
- X{
- X if (addr < 0x300000 &&
- X (addr < fid->ef_dbase || addr > fid->ef_end))
- X {
- X (void) fprintf(stderr, "Invalid data address %lx\n", addr);
- X exit(200);
- X }
- X addr -= fid->ef_dbase;
- X (void) lseek(fid->ef_d, (long)(addr * sizeof(d_entry)), 0);
- X (void) write(fid->ef_d, (char *) de, sizeof(d_entry));
- X}
- X
- X/*
- X * Set type and length of given data entry.
- X */
- X
- Xvoid setde(fid, addr, type, lng)
- Xef_fid fid;
- Xlong addr;
- Xunsigned type;
- Xint lng;
- X{
- X d_entry dat;
- X
- X if (addr > fid->ef_end)
- X return;
- X getde(fid, addr, &dat);
- X if (type == D_CONT && dat.d_reloc != R_NONE) {
- X char obuf[30];
- X (void) sprintf(obuf, "overlapped reloc 0x%x", addr);
- X unimpl(obuf);
- X }
- X dat.d_type = type;
- X dat.d_lng = lng;
- X putde(fid, addr, &dat);
- X}
- X
- X/*
- X * Get a word of data file, size as requested.
- X */
- X
- Xlong getdw(fid, pos, size)
- Xregister ef_fid fid;
- Xlong pos;
- Xint size;
- X{
- X d_entry dat;
- X register long res;
- X register int i, lt;
- X
- X getde(fid, pos, &dat);
- X
- X switch (size) {
- X case R_BYTE:
- X return dat.d_contents;
- X
- X case R_LONG:
- X lt = 4;
- X goto rest;
- X
- X case R_WORD:
- X lt = 2;
- X rest:
- X res = dat.d_contents;
- X for (i = 1; i < lt; i++) {
- X getde(fid, pos+i, &dat);
- X res = (res << 8) + dat.d_contents;
- X }
- X return res;
- X
- X default:
- X (void) fprintf(stderr, "Data word size error\n");
- X exit(20);
- X }
- X /*NOTREACHED*/
- X}
- X
- X/*
- X * Get a word of text file.
- X */
- X
- Xlong gettw(fid, pos, size)
- Xregister ef_fid fid;
- Xlong pos;
- Xint size;
- X{
- X t_entry tex;
- X long res;
- X
- X gette(fid, pos, &tex);
- X
- X switch (size) {
- X case R_BYTE:
- X return tex.t_contents >> 8;
- X
- X case R_WORD:
- X return tex.t_contents;
- X
- X case R_LONG:
- X res = tex.t_contents;
- X gette(fid, pos+2, &tex);
- X return (res << 16) + tex.t_contents;
- X default:
- X (void) fprintf(stderr, "Text< word size error\n");
- X exit(20);
- X }
- X /*NOTREACHED*/
- X}
- SHAR_EOF
- chmod 0644 file.c || echo "restore of file.c fails"
- sed 's/^X//' << 'SHAR_EOF' > heur.c &&
- X/*
- X * SCCS: @(#)heur.c 1.2 11/2/84 14:17:46
- X * Attempt to guess things about the file.
- X *
- X ***********************************************************************
- X * This software is copyright of
- X *
- X * John M Collins
- X * 47 Cedarwood Drive
- X * St Albans
- X * Herts, AL4 0DN
- X * England +44 727 57267
- X *
- X * and is released into the public domain on the following conditions:
- X *
- X * 1. No free maintenance will be guaranteed.
- X * 2. Nothing may be based on this software without
- X * acknowledgement, including incorporation of this
- X * notice.
- X *
- X * Notwithstanding the above, the author welcomes correspondence and bug
- X * fixes.
- X ***********************************************************************
- X */
- X
- X#include <stdio.h>
- X#include <a.out.h>
- X#include <ldfcn.h>
- X#include "unc.h"
- X
- X#define INITDAT 256
- X#define INCDAT 128
- X
- X#define STRSCNT 3
- X#define STRECNT 3
- X
- Xchar *malloc(), *realloc();
- X
- Xvoid gette(), getde(), setde(), putte(), putde();
- Xvoid nomem();
- Xlong getdw();
- Xsymbol inventsymb();
- X
- Xlong endt;
- Xef_fids mainfile;
- X
- X/*
- X * Talk about implemented things.....
- X */
- X
- Xvoid unimpl(msg)
- Xchar *msg;
- X{
- X (void) fprintf(stderr, "Warning: handling of \"%s\" not implemented\n", msg);
- X}
- X
- X/*
- X * Return 1 if string char, otherwise 0.
- X */
- X
- Xint possstr(x)
- Xunsigned x;
- X{
- X if (x >= ' ' && x <= '~')
- X return 1;
- X if (x == '\n' || x == '\t')
- X return 1;
- X return 0;
- X}
- X
- X/*
- X * Guess things about data files.
- X */
- X
- Xvoid intudat(fid)
- Xef_fid fid;
- X{
- X register int i, j;
- X int lt, input, invcnt;
- X long offs, soffs, endd;
- X d_entry fdat;
- X unsigned char *inbuf;
- X int ibsize;
- X
- X inbuf = (unsigned char *)malloc(INITDAT);
- X if (inbuf == NULL)
- X nomem();
- X ibsize = INITDAT;
- X
- X offs = fid->ef_dbase;
- X endd = fid->ef_bbase;
- X
- X while (offs < endd) {
- X getde(fid, offs, &fdat);
- X if (fdat.d_type != D_BYTE) {
- X offs += fdat.d_lng;
- X continue;
- X }
- X
- X /*
- X * Looks like general data. Read in as much as possible.
- X */
- X
- X input = 0;
- X soffs = offs;
- X do {
- X if (input >= ibsize) {
- X ibsize += INCDAT;
- X inbuf = (unsigned char *)
- X realloc((char *)inbuf, (unsigned)ibsize);
- X if (inbuf == NULL)
- X nomem();
- X }
- X inbuf[input++] = fdat.d_contents;
- X offs++;
- X if (offs >= endd)
- X break;
- X getde(fid, offs, &fdat);
- X } while (fdat.d_type == D_BYTE && fdat.d_lab == NULL);
- X
- X /*
- X * Now split up the data.
- X */
- X
- X for (i = 0; i < input; ) {
- X
- X /*
- X * Might be a string.
- X */
- X
- X if (possstr(inbuf[i])) {
- X lt = input;
- X if (i + STRSCNT < lt)
- X lt = i + STRSCNT;
- X for (j = i + 1; j < lt; j++) {
- X if (inbuf[j] == '\0')
- X break;
- X if (!possstr(inbuf[j]))
- X goto notstr;
- X }
- X
- X /*
- X * Looks like a string then.
- X */
- X
- X invcnt = 0;
- X for (j = i + 1; j < input; j++) {
- X if (inbuf[j] == '\0') {
- X j++;
- X break;
- X }
- X if (possstr(inbuf[j]))
- X invcnt = 0;
- X else {
- X invcnt++;
- X if (invcnt >= STRECNT) {
- X j -= invcnt - 1;
- X break;
- X }
- X }
- X }
- X
- X setde(fid,
- X soffs+i,
- X (unsigned)(inbuf[j-1]=='\0'?D_ASCZ:D_ASC),
- X j - i);
- X for (i++; i < j; i++)
- X setde(fid, soffs+i, D_CONT, 1);
- X continue;
- X }
- X
- Xnotstr:
- X /*
- X * If on odd boundary, treat as a byte.
- X */
- X
- X if ((soffs + i) & 1 || i + 1 >= input) {
- X setde(fid, soffs + i, D_BYTE, 1);
- X i++;
- X continue;
- X }
- X
- X /*
- X * Treat as longs unless not enough.
- X */
- X
- X if (i + 3 >= input) {
- X setde(fid, soffs + i, D_WORD, 2);
- X setde(fid, soffs + i + 1, D_CONT, -1);
- X i += 2;
- X continue;
- X }
- X
- X /*
- X * Treat as a long but mark changable.
- X */
- X
- X setde(fid, soffs + i, D_LONG, 4);
- X for (j = 1; j < 4; j++)
- X setde(fid, soffs + i + j, D_CONT, -j);
- X i += 4;
- X }
- X }
- X free((char *)inbuf);
- X
- X /*
- X * Now zap bss segment.
- X */
- X
- X offs = fid->ef_bbase;
- X endd = fid->ef_end;
- X
- X while (offs < endd) {
- X getde(fid, offs, &fdat);
- X if (fdat.d_type != D_BYTE) {
- X offs += fdat.d_lng;
- X continue;
- X }
- X
- X soffs = offs;
- X do {
- X offs++;
- X if (offs >= endd)
- X break;
- X getde(fid, offs, &fdat);
- X } while (fdat.d_type == D_BYTE && fdat.d_lab == NULL);
- X
- X setde(fid, soffs, D_BYTE, (int)(offs-soffs));
- X for (i = -1, soffs++; soffs < offs; i--, soffs++)
- X setde(fid, soffs, D_CONT, i);
- X }
- X}
- X
- X/*
- X * For non relocatable files, try to identify address pointers in
- X * the data.
- X */
- X
- Xvoid inturdat(fid)
- Xef_fid fid;
- X{
- X register long offs = fid->ef_dbase;
- X register int i;
- X register symbol ds;
- X long endd = fid->ef_bbase;
- X long cont;
- X d_entry dent, refdent;
- X
- X while (offs < endd) {
- X getde(fid, offs, &dent);
- X if (dent.d_type != D_LONG)
- X goto endit;
- X cont = getdw(fid, offs, R_LONG);
- X if (cont < fid->ef_dbase || cont > fid->ef_end)
- X goto endit;
- X getde(fid, cont, &refdent);
- X if (refdent.d_type == D_CONT) {
- X d_entry pdent;
- X int siz;
- X
- X if (refdent.d_lng >= 0)
- X goto endit;
- X getde(fid, cont+refdent.d_lng, &pdent);
- X i = -refdent.d_lng;
- X refdent.d_lng += pdent.d_lng;
- X pdent.d_lng = i;
- X if (pdent.d_type == D_LONG && i == 2)
- X siz = D_WORD;
- X else
- X siz = D_BYTE;
- X refdent.d_type = siz;
- X pdent.d_type = siz;
- X putde(fid, cont - i, &pdent);
- X for (i = 1; i < refdent.d_lng; i++)
- X setde(fid, cont+i, D_CONT, -i);
- X }
- X if ((ds = refdent.d_lab) == NULL) {
- X if (cont >= fid->ef_bbase) {
- X ds = inventsymb("BS");
- X ds->s_type = S_BSS;
- X }
- X else {
- X ds = inventsymb("DS");
- X ds->s_type = S_DATA;
- X }
- X ds->s_value = cont;
- X refdent.d_lab = ds;
- X putde(fid, cont, &refdent);
- X }
- X else
- X ds->s_used++;
- X dent.d_type = D_ADDR;
- X dent.d_relsymb = ds;
- X dent.d_rptr = ds->s_type;
- X putde(fid, offs, &dent);
- X for (i = 1; i < 4; i++)
- X setde(fid, offs+i, D_CONT, 1);
- Xendit:
- X offs += dent.d_lng;
- X }
- X}
- X
- X/*
- X * Recursively follow through the code, stopping at unconditional
- X * branches and invalid instructions.
- X */
- X
- Xvoid follseq(pos)
- Xlong pos;
- X{
- X t_entry tent;
- X int lng;
- X long npos;
- X
- X while (pos < endt) {
- X gette(&mainfile, pos, &tent);
- X if (tent.t_amap) /* Been here */
- X return;
- X tent.t_amap = 1;
- X lng = findinst(&tent, pos);
- X npos = pos + lng*2;
- X if (npos > endt) {
- X tent.t_vins = 0;
- X tent.t_lng = 1;
- X tent.t_type = T_UNKNOWN;
- X lng = 0;
- X npos = endt;
- X }
- X putte(&mainfile, pos, &tent);
- X pos = npos;
- X
- X if (lng <= 0)
- X return;
- X
- X switch (tent.t_bchtyp) {
- X case T_UNBR:
- X if (tent.t_relsymb == NULL)
- X return;
- X pos = tent.t_relsymb->s_value;
- X continue;
- X case T_JSR:
- X if (tent.t_relsymb != NULL)
- X follseq(tent.t_relsymb->s_value);
- X continue;
- X case T_CONDBR:
- X follseq(tent.t_relsymb->s_value);
- X default:
- X continue;
- X }
- X }
- X}
- X
- X
- X/*
- X * Try to work out things about text files.
- X */
- X
- Xvoid intutext()
- X{
- X long pos;
- X t_entry tent;
- X int lng;
- X
- X endt = mainfile.ef_tbase + mainfile.ef_tsize;
- X pos = mainfile.ef_entry;
- Xnextv:
- X for (; pos < endt;) {
- X gette(&mainfile, pos, &tent);
- X if (!tent.t_amap && tent.t_vins) {
- X follseq(pos);
- X pos += 2;
- X goto nextiv;
- X }
- X pos += tent.t_lng * 2;
- X if (tent.t_bchtyp == T_UNBR)
- X goto nextiv;
- X }
- X goto dorest;
- Xnextiv:
- X for (; pos < endt; pos += 2) {
- X gette(&mainfile, pos, &tent);
- X if (tent.t_bdest)
- X goto nextv;
- X }
- Xdorest:
- X /*
- X * Deal with unmapped instructions.
- X */
- X
- X for (pos = mainfile.ef_tbase; pos < endt;) {
- X gette(&mainfile, pos, &tent);
- X switch (tent.t_type) {
- X case T_BEGIN:
- X pos += tent.t_lng * 2;
- X continue;
- X case T_UNKNOWN:
- X if (tent.t_vins) {
- X lng = findinst(&tent, pos);
- X putte(&mainfile, pos, &tent);
- X if (lng > 0) {
- X pos += lng * 2;
- X continue;
- X }
- X }
- X default:
- X pos += 2;
- X continue;
- X }
- X }
- X}
- X
- X/*
- X * Invent local symbols.
- X */
- X
- Xvoid intlsym()
- X{
- X long bpos, epos, hiref, hipos;
- X unsigned llnum;
- X t_entry tent;
- X register symbol tl;
- X
- X endt = mainfile.ef_tbase + mainfile.ef_tsize;
- X epos = mainfile.ef_entry;
- X for (;;) {
- X bpos = epos;
- X hiref = bpos;
- X if (epos >= endt)
- X return;
- X gette(&mainfile, epos, &tent);
- X epos += tent.t_lng * 2;
- X for (; epos < endt;) {
- X gette(&mainfile, epos, &tent);
- X if (tent.t_gbdest || tent.t_dref)
- X break;
- X if (tent.t_reflo < bpos)
- X break;
- X if (tent.t_refhi > hiref) {
- X hiref = tent.t_refhi;
- X hipos = epos;
- X }
- X epos += tent.t_lng * 2;
- X }
- X if (hiref > epos)
- X epos = hipos;
- X llnum = 0;
- X for (hipos = bpos; hipos < epos;) {
- X gette(&mainfile, hipos, &tent);
- X if (!tent.t_gbdest && !tent.t_dref &&
- X tent.t_reflo >= bpos && tent.t_refhi < epos &&
- X (tl = tent.t_lab) != NULL)
- X tl->s_lsymb = ++llnum;
- X hipos += tent.t_lng * 2;
- X }
- X }
- X}
- X
- X/*
- X * Given the main file, a possible candidate for matching in the
- X * file and an offset, see if text matches. Return 1 if matches,
- X * or 0 if no match.
- X */
- X
- Xint matchup(mf, lf, startpos)
- Xregister ef_fid mf, lf;
- Xlong startpos;
- X{
- X register int i, matches = 0;
- X t_entry ltent, mtent;
- X
- X if (lf->ef_tsize > mf->ef_tsize - startpos + mf->ef_tbase)
- X return 0; /* At end - can't fit */
- X
- X for (i = 0; i < lf->ef_tsize; i += 2) {
- X gette(lf, lf->ef_tbase + i, <ent);
- X if (ltent.t_isrel)
- X continue;
- X gette(mf, startpos + i, &mtent);
- X if (mtent.t_contents != ltent.t_contents)
- X return 0;
- X matches++;
- X }
- X
- X /*
- X * Give up on zero length or all relocatable files.
- X */
- X
- X return matches > 0;
- X}
- X
- X/*
- X * Scan through main file looking for a match.
- X */
- X
- Xlong findstart(mf, lf)
- Xregister ef_fid mf, lf;
- X{
- X register long res = mf->ef_tbase;
- X long lim = mf->ef_tbase + mf->ef_tsize - lf->ef_tsize;
- X t_entry tent;
- X
- Xrestart:
- X for (; res <= lim; res += 2) {
- X gette(mf, res, &tent);
- X if (tent.t_match != 0) {
- X res += tent.t_match;
- X goto restart;
- X }
- X if (matchup(mf, lf, res))
- X return res;
- X }
- X return -1;
- X}
- X
- X/*
- X * Mark the head of a matched module to save searching.
- X */
- X
- Xvoid markmatch(mf, lf, pos)
- Xef_fid mf, lf;
- Xlong pos;
- X{
- X t_entry tent;
- X
- X gette(mf, pos, &tent);
- X tent.t_match = (unsigned) lf->ef_tsize;
- X putte(mf, pos, &tent);
- X}
- SHAR_EOF
- chmod 0644 heur.c || echo "restore of heur.c fails"
- sed 's/^X//' << 'SHAR_EOF' > main.c &&
- X/*
- X * SCCS: @(#)main.c 1.2 11/2/84 14:19:31
- X * Main routine etc.
- X *
- X ***********************************************************************
- X * This software is copyright of
- X *
- X * John M Collins
- X * 47 Cedarwood Drive
- X * St Albans
- X * Herts, AL4 0DN
- X * England +44 727 57267
- X *
- X * and is released into the public domain on the following conditions:
- X *
- X * 1. No free maintenance will be guaranteed.
- X * 2. Nothing may be based on this software without
- X * acknowledgement, including incorporation of this
- X * notice.
- X *
- X * Notwithstanding the above, the author welcomes correspondence and bug
- X * fixes.
- X ***********************************************************************
- X */
- X
- X#include <stdio.h>
- X#include <fcntl.h>
- X#include <a.out.h>
- X#include <ldfcn.h>
- X#include "unc.h"
- X
- X#define LINELNG 70
- X
- Xvoid inturdat(), intutext(), intudat(), intlsym();
- Xvoid ptext(), pdata(), pabs(), pbss(), lscan();
- X
- Xef_fids mainfile;
- X
- Xint nmods; /* Number of modules it looks like */
- X
- Xchar *tfnam = "split";
- X
- Xchar lsyms; /* Generate local symbols */
- Xchar verbose; /* Tell the world what we are doing */
- Xchar noabs; /* No non-global absolutes */
- Xint rel; /* File being analysed is relocatable */
- Xint lpos;
- Xchar shlibout; /* output values for shlib constants */
- X
- Xsymbol dosymb();
- Xstruct libit *getfnam();
- X
- X/*
- X * Get hex characters, also allowing for 'k' and 'm'.
- X */
- X
- Xint ghex(str)
- Xregister char *str;
- X{
- X register int result = 0;
- X register int lt;
- X
- X for (;;) {
- X lt = *str++;
- X switch (lt) {
- X default:
- Xerr: (void) fprintf(stderr, "Invalid hex digit \'%c\'\n", lt);
- X exit(1);
- X
- X case '\0':
- X return result;
- X
- X case '0':case '1':case '2':case '3':case '4':
- X case '5':case '6':case '7':case '8':case '9':
- X result = (result << 4) + lt - '0';
- X continue;
- X
- X case 'a':case 'b':case 'c':case 'd':case 'e':case 'f':
- X result = (result << 4) + lt - 'a' + 10;
- X continue;
- X
- X case 'A':case 'B':case 'C':case 'D':case 'E':case 'F':
- X result = (result << 4) + lt - 'A' + 10;
- X continue;
- X
- X case 'k':case 'K':
- X if (*str != '\0')
- X goto err;
- X return result << 10;
- X
- X case 'm':case 'M':
- X if (*str != '\0')
- X goto err;
- X return result << 20;
- X }
- X }
- X}
- X
- X/*
- X * Process entry line options. Return number dealt with.
- X */
- X
- Xint doopts(av)
- Xchar *av[];
- X{
- X register int cnt = 0, lt;
- X register char *arg;
- X
- X for (;;) {
- X arg = *++av;
- X if (*arg++ != '-')
- X return cnt;
- X cnt++;
- X
- Xnx: switch (lt = *arg++) {
- X default:
- X (void) fprintf(stderr, "Bad option -%c\n", lt);
- X exit(1);
- X
- X case '\0':
- X continue;
- X
- X case 'l': /* A file name */
- X case 'L':
- X return cnt - 1;
- X
- X case 's':
- X lsyms++;
- X goto nx;
- X
- X case 'v':
- X verbose++;
- X goto nx;
- X
- X case 'V':
- X shlibout++;
- X goto nx;
- X
- X case 'a':
- X noabs++;
- X goto nx;
- X
- X case 't':
- X if (*arg == '\0') {
- X cnt++;
- X arg = *++av;
- X if (arg == NULL) {
- Xbo: (void) fprintf(stderr,"Bad -%c option\n",lt);
- X exit(1);
- X }
- X }
- X tfnam = arg;
- X continue;
- X
- X case 'o':
- X if (*arg == '\0') {
- X cnt++;
- X arg = *++av;
- X if (arg == NULL)
- X goto bo;
- X }
- X if (freopen(arg, "w", stdout) == NULL) {
- X (void) fprintf(stderr, "Help! cant open %s\n", arg);
- X exit(20);
- X }
- X continue;
- X }
- X }
- X}
- X
- X/*
- X * Open binary files. Arrange to erase them when finished.
- X */
- X
- Xvoid bfopen(nam, fid)
- Xchar *nam;
- Xef_fid fid;
- X{
- X char fnam[80];
- X
- X (void) sprintf(fnam, "%s.tx", nam);
- X if ((fid->ef_t = open(fnam, O_RDWR|O_CREAT, 0666)) < 0) {
- Xefil: (void) fprintf(stderr, "Help could not open %s\n", fnam);
- X exit(4);
- X }
- X (void) unlink(fnam);
- X (void) sprintf(fnam, "%s.dt", nam);
- X if ((fid->ef_d = open(fnam, O_RDWR|O_CREAT, 0666)) < 0)
- X goto efil;
- X (void) unlink(fnam);
- X}
- X
- X/*
- X * Close binary files. They should get zapped anyway.
- X */
- X
- Xvoid bfclose(fid)
- Xef_fid fid;
- X{
- X (void) close(fid->ef_t);
- X (void) close(fid->ef_d);
- X}
- X
- X/*
- X * Main routine.
- X */
- X
- Xmain(argc, argv)
- Xint argc;
- Xchar *argv[];
- X{
- X int i;
- X char *progname = argv[0];
- X char *msg;
- X register struct libit *lfd;
- X
- X setbuf(stdout,NULL);
- X setbuf(stderr,NULL);
- X
- X i = doopts(argv);
- X argc -= i;
- X argv += i;
- X
- X if (argc < 2) {
- X (void) fprintf(stderr, "Usage: %s [ options ] file\n", progname);
- X exit(1);
- X }
- X
- X lfd = getfnam(argv[1]);
- X if (TYPE(lfd->ldptr) == ARTYPE) {
- X (void) fprintf(stderr, "Main file (%s) cannot be library\n", argv[1]);
- X exit(2);
- X }
- X
- X bfopen(tfnam, &mainfile);
- X if (verbose)
- X (void) fprintf(stderr, "Scanning text\n");
- X if (!rtext(lfd->ldptr, &mainfile)) {
- X msg = "text";
- Xbf: (void) fprintf(stderr, "Bad format input file - reading %s\n", msg);
- X exit(5);
- X }
- X if (verbose)
- X (void) fprintf(stderr, "Scanning data\n");
- X if (!rdata(lfd->ldptr, &mainfile)) {
- X msg = "data";
- X goto bf;
- X }
- X if (verbose)
- X (void) fprintf(stderr, "Scanning symbols\n");
- X if (!rsymb(lfd->ldptr, dosymb, &mainfile)) {
- X msg = "symbols";
- X goto bf;
- X }
- X if (verbose)
- X (void) fprintf(stderr, "Scanning for relocation\n");
- X if ((rel = rrel(lfd->ldptr, lfd->ldptr2, &mainfile)) < 0) {
- X msg = "reloc";
- X goto bf;
- X }
- X
- X if (rel) {
- X if (verbose)
- X (void) fprintf(stderr, "File is relocatable\n");
- X if (argc > 2)
- X (void) fprintf(stderr, "Sorry - no scan on reloc files\n");
- X }
- X else
- X lscan(argc - 2, &argv[2]);
- X
- X if (verbose)
- X (void) fprintf(stderr, "End of input\n");
- X
- X ldaclose(lfd->ldptr2);
- X ldclose(lfd->ldptr);
- X if (nmods > 0)
- X (void) fprintf(stderr, "Warning: at least %d merged modules\n",
- X nmods + 1);
- X
- X if (mainfile.ef_stvec != NULL) {
- X free(mainfile.ef_stvec);
- X mainfile.ef_stvec = NULL;
- X mainfile.ef_stcnt = 0;
- X }
- X
- X if (verbose)
- X (void) fprintf(stderr, "Text anal 1\n");
- X intutext();
- X if (verbose)
- X (void) fprintf(stderr, "Data anal 1\n");
- X intudat(&mainfile);
- X if (!rel) {
- X if (verbose)
- X (void) fprintf(stderr, "Data anal 2\n");
- X inturdat(&mainfile);
- X }
- X if (lsyms) {
- X if (verbose)
- X (void) fprintf(stderr, "Local symbol scan\n");
- X intlsym();
- X }
- X pabs();
- X ptext(&mainfile);
- X pdata(&mainfile);
- X pbss(&mainfile);
- X bfclose(&mainfile);
- X exit(0);
- X}
- SHAR_EOF
- chmod 0644 main.c || echo "restore of main.c fails"
- sed 's/^X//' << 'SHAR_EOF' > prin.c &&
- X/*
- X * SCCS: @(#)prin.c 1.2 11/2/84 14:19:47
- X * Print stuff.
- X *
- X ***********************************************************************
- X * This software is copyright of
- X *
- X * John M Collins
- X * 47 Cedarwood Drive
- X * St Albans
- X * Herts, AL4 0DN
- X * England +44 727 57267
- X *
- X * and is released into the public domain on the following conditions:
- X *
- X * 1. No free maintenance will be guaranteed.
- X * 2. Nothing may be based on this software without
- X * acknowledgement, including incorporation of this
- X * notice.
- X *
- X * Notwithstanding the above, the author welcomes correspondence and bug
- X * fixes.
- X ***********************************************************************
- X */
- X
- X#include <stdio.h>
- X#include <a.out.h>
- X#include <ldfcn.h>
- X#include "unc.h"
- X
- X#define LINELNG 70
- X
- Xvoid gette(), getde();
- Xlong gettw(), getdw();
- Xvoid prinst();
- X
- Xchar noabs; /* No non-global absolutes */
- Xint rel; /* File being analysed is relocatable */
- Xint lpos;
- X
- Xstruct commit abstab, comtab;
- Xextern char shlibout;
- X
- X/*
- X * Print absolute and common values.
- X */
- X
- Xvoid pabs()
- X{
- X register int i;
- X register symbol cs;
- X
- X for (i = 0; i < abstab.c_int; i++)
- X
- X for (i = 0; i < abstab.c_int; i++) {
- X cs = abstab.c_symb[i];
- X if (cs->s_value >= 0x300000 && ! shlibout)
- X continue;
- X if (cs->s_glob)
- X (void) printf("#\tglobal\t%s\n", cs->s_name);
- X else if (noabs)
- X continue;
- X (void) printf("# %s\t= 0x%lx\n", cs->s_name, cs->s_value);
- X }
- X for (i = 0; i < comtab.c_int; i++) {
- X cs = comtab.c_symb[i];
- X (void) printf("\tcomm\t%s,%d\n", cs->s_name, cs->s_value);
- X }
- X}
- X
- X/*
- X * Print out labels.
- X */
- X
- Xvoid plabs(ls, seg)
- Xregister symbol ls;
- Xint seg;
- X{
- X for (; ls != NULL; ls = ls->s_link) {
- X if (ls->s_type != seg)
- X continue;
- X if (ls->s_lsymb) {
- X (void) printf("L%%%u:\n", ls->s_lsymb);
- X return; /* Set last */
- X }
- X if (ls->s_glob)
- X (void) printf("\n\tglobal\t%s", ls->s_name);
- X if (ls->s_name[0] == '.')
- X (void) printf("\n# %s:\n", ls->s_name);
- X else
- X (void) printf("\n%s:\n", ls->s_name);
- X }
- X}
- X
- X/*
- X * Print out text.
- X */
- X
- Xvoid ptext(fid)
- Xregister ef_fid fid;
- X{
- X register long tpos, endt;
- X t_entry tstr;
- X
- X (void) fputs("\ttext\n", stdout);
- X
- X tpos = fid->ef_tbase;
- X endt = tpos + fid->ef_tsize;
- Xcontin:
- X for (; tpos < endt; tpos += tstr.t_lng * 2) {
- X gette(fid, tpos, &tstr);
- X plabs(tstr.t_lab, S_TEXT);
- X if (tstr.t_type == T_BEGIN)
- X prinst(&tstr, tpos);
- X else if (tstr.t_relsymb != NULL) {
- X (void) printf("\tlong\t%s", tstr.t_relsymb->s_name);
- X if (tstr.t_relsymb->s_type!=S_TEXT &&
- X tstr.t_relsymb->s_type!=S_DATA)
- X (void) printf("+0x%x", gettw(fid, tpos, R_LONG));
- X (void) putchar('\n');
- X tpos += 4;
- X goto contin;
- X }
- X else
- X (void) printf("\tshort\t0x%x\n", tstr.t_contents);
- X }
- X
- X /*
- X * Print out any trailing label.
- X */
- X
- X gette(fid, tpos, &tstr);
- X plabs(tstr.t_lab, S_TEXT);
- X}
- X
- X/*
- X * Print out data.
- X */
- X
- Xvoid pdata(fid)
- Xregister ef_fid fid;
- X{
- X register long dpos, endd;
- X register int lng, ccnt;
- X unsigned ctyp;
- X int had, par, inc;
- X char *msg;
- X d_entry dstr;
- X
- X (void) fputs("\n\tdata\n", stdout);
- X
- X dpos = fid->ef_dbase;
- X endd = dpos + fid->ef_dsize;
- X
- X while (dpos < endd) {
- X
- X getde(fid, dpos, &dstr);
- X plabs(dstr.d_lab, S_DATA);
- X
- X switch (dstr.d_type) {
- X case D_CONT:
- X (void) fprintf(stderr, "Data sync error\n");
- X dpos++;
- X break;
- X
- X case D_ASC:
- X case D_ASCZ:
- X ctyp = dstr.d_type;
- X lng = dstr.d_lng;
- X nextline:
- X (void) fputs("\tbyte\t", stdout);
- X ccnt=0;
- X while (lng > 0) {
- X if (ccnt) (void) putchar(',');
- X getde(fid, dpos, &dstr);
- X switch (dstr.d_contents) {
- X default:
- X if (dstr.d_contents < ' ' ||
- X dstr.d_contents > '~')
- X ccnt += printf("0x%x", dstr.d_contents);
- X else {
- X (void) putchar('\'');
- X (void)putchar(dstr.d_contents);
- X ccnt += 2;
- X }
- X break;
- X case '\\':
- X (void) putchar('\'');
- X (void) putchar('\\');
- X (void) putchar('\\');
- X ccnt+=2;
- X break;
- X case '\b':
- X (void) putchar('\'');
- X (void) putchar('\\');
- X (void) putchar('b');
- X ccnt+=2;
- X break;
- X case '\n':
- X (void) putchar('\'');
- X (void) putchar('\\');
- X (void) putchar('n');
- X ccnt+=2;
- X break;
- X case '\r':
- X (void) putchar('\'');
- X (void) putchar('\\');
- X (void) putchar('r');
- X ccnt+=2;
- X break;
- X case '\f':
- X (void) putchar('\'');
- X (void) putchar('\\');
- X (void) putchar('f');
- X ccnt+=2;
- X break;
- X case '\t':
- X (void) putchar('\'');
- X (void) putchar('\\');
- X (void) putchar('t');
- X ccnt+=2;
- X break;
- X }
- X
- X lng--;
- X dpos++;
- X if (++ccnt > 40 && lng > 0) {
- X (void) putchar('\n');
- X goto nextline;
- X }
- X }
- X (void) putchar('\n');
- X break;
- X
- X case D_BYTE:
- X msg = "byte";
- X par = R_BYTE;
- X inc = 1;
- X goto wrest;
- X
- X case D_WORD:
- X msg = "short";
- X par = R_WORD;
- X inc = 2;
- X goto wrest;
- X
- X case D_LONG:
- X msg = "long";
- X par = R_LONG;
- X inc = 4;
- X wrest:
- X (void) putchar('\t');
- X (void) fputs(msg, stdout);
- X (void) putchar('\t');
- X lng = dstr.d_lng;
- X lpos = 16;
- X had = 0;
- X while (lng > 0) {
- X if (lpos > LINELNG) {
- X (void) putchar('\n');
- X (void) putchar('\t');
- X (void) fputs(msg, stdout);
- X (void) putchar('\t');
- X lpos = 16;
- X }
- X else if (had) {
- X (void) putchar(',');
- X (void) putchar(' ');
- X lpos += 2;
- X }
- X lpos += printf("0x%x", getdw(fid, dpos, par));
- X lng -= inc;
- X dpos += inc;
- X had++;
- X }
- X (void) putchar('\n');
- X break;
- X
- X case D_ADDR:
- X (void) fputs("\tlong\t", stdout);
- X lng = dstr.d_lng;
- X lpos = 16;
- X had = 0;
- X while (lng > 0) {
- X if (lpos > LINELNG) {
- X (void) fputs("\n\tlong\t", stdout);
- X lpos = 16;
- X }
- X else if (had) {
- X (void) putchar(',');
- X (void) putchar(' ');
- X lpos += 2;
- X }
- X
- X getde(fid, dpos, &dstr);
- X lpos += printf("%s", dstr.d_relsymb->s_name);
- X lng -= sizeof(long);
- X dpos += sizeof(long);
- X had++;
- X }
- X (void) putchar('\n');
- X break;
- X }
- X }
- X
- X /*
- X * Print trailing label.
- X */
- X
- X getde(fid, dpos, &dstr);
- X plabs(dstr.d_lab, S_DATA);
- X}
- X
- Xvoid pbss(fid)
- Xregister ef_fid fid;
- X{
- X register long bpos = fid->ef_bbase;
- X long endb = fid->ef_end;
- X d_entry bstr;
- X
- X (void) fputs("\n# .bss\n", stdout);
- X
- X while (bpos < endb) {
- X getde(fid, bpos, &bstr);
- X plabs(bstr.d_lab, S_BSS);
- X (void) printf("\tspace\t%d\n", bstr.d_lng);
- X bpos += bstr.d_lng;
- X }
- X
- X getde(fid, endb, &bstr);
- X plabs(bstr.d_lab, S_BSS);
- X}
- X
- X
- SHAR_EOF
- chmod 0644 prin.c || echo "restore of prin.c fails"
- sed 's/^X//' << 'SHAR_EOF' > unc.h &&
- X/*
- X * SCCS: @(#)unc.h 1.2 11/2/84 14:21:02
- X * Header file for uncompile program.
- X *
- X ***********************************************************************
- X * This software is copyright of
- X *
- X * John M Collins
- X * 47 Cedarwood Drive
- X * St Albans
- X * Herts, AL4 0DN
- X * England +44 727 57267
- X *
- X * and is released into the public domain on the following conditions:
- X *
- X * 1. No free maintenance will be guaranteed.
- X * 2. Nothing may be based on this software without
- X * acknowledgement, including incorporation of this
- X * notice.
- X *
- X * Notwithstanding the above, the author welcomes correspondence and bug
- X * fixes.
- X ***********************************************************************
- X */
- X
- X#define MAXCHARS 50
- X#define HASHMOD 97
- X
- X/*
- X * The following structure is used to keep track of symbols.
- X */
- X
- Xstruct symstr {
- X struct symstr *s_next; /* Next in hash chain */
- X struct symstr *s_link; /* Next in duplicate labels */
- X unsigned s_type : 5; /* Symbol type */
- X unsigned s_newsym: 1; /* A new symbol */
- X unsigned s_invent: 1; /* Invented symbol */
- X unsigned s_glob : 1; /* Global symbol */
- X long s_value; /* Value if defined */
- X short s_defs; /* Defined count */
- X short s_used; /* Used count */
- X unsigned short s_lsymb; /* Local symbol */
- X char s_name[1]; /* Chars of name null term */
- X};
- X
- Xtypedef struct symstr *symbol;
- X
- Xsymbol symbhash[HASHMOD];
- X
- Xtypedef struct {
- X int ef_t; /* Text file fd */
- X int ef_d; /* Data file fd */
- X long ef_entry; /* Entry point */
- X long ef_tsize; /* Text size */
- X long ef_dsize; /* Data size */
- X long ef_bsize; /* Bss size */
- X long ef_end; /* End of it all */
- X long ef_tbase; /* Text base */
- X long ef_dbase; /* Data base */
- X long ef_bbase; /* Bss base */
- X int ef_stcnt; /* Number of symbols */
- X int ef_stmax; /* Max number of symbols */
- X symbol *ef_stvec; /* Symbol vector */
- X} ef_fids;
- X
- Xtypedef ef_fids *ef_fid;
- X
- X/*
- X * Description of word in text file. This entry is held in the place
- X * corresponding to the address in the text file.
- X */
- X
- Xtypedef struct {
- X unsigned short t_contents; /* Actual contents */
- X unsigned short t_iindex; /* Index in table */
- X unsigned t_type : 2; /* Type */
- X unsigned t_vins : 1; /* Valid instruction */
- X unsigned t_bdest : 1; /* Is branch dest */
- X unsigned t_gbdest: 1; /* Is global dest */
- X unsigned t_dref : 1; /* Refered to in data */
- X unsigned t_bchtyp: 2; /* Branch type */
- X unsigned t_zilch : 3; /* used to be t_lng */
- X unsigned t_reloc : 2; /* Relocatable */
- X unsigned t_rptr : 2; /* Where relocated */
- X unsigned t_rdisp : 1; /* Relocatable displacement */
- X unsigned t_isrel : 1; /* Relocated */
- X unsigned t_amap : 1; /* Worked out */
- X short t_lng; /* Length in words */
- X symbol t_relsymb; /* Relocation symbol */
- X long t_reldisp; /* Offset + or - from symb */
- X symbol t_lab; /* Label */
- X unsigned short t_lsymb; /* Local symbol */
- X long t_reflo; /* Lowest place referred */
- X long t_refhi; /* Highest place referred */
- X unsigned short t_match; /* Lib match lng */
- X} t_entry;
- X
- X/*
- X * Types ......
- X */
- X
- X#define T_UNKNOWN 0
- X#define T_BEGIN 1
- X#define T_CONT 2
- X
- X#define R_NONE 0 /* No relocation */
- X#define R_BYTE 1 /* Byte relocation */
- X#define R_WORD 2 /* Word relocation */
- X#define R_LONG 3 /* Long relocation */
- X
- X/*
- X * Branch types.
- X */
- X
- X#define T_NOBR 0
- X#define T_CONDBR 1
- X#define T_UNBR 2
- X#define T_JSR 3
- X
- Xtypedef struct {
- X unsigned char d_contents; /* Actual contents */
- X unsigned d_type : 4; /* Data type */
- X unsigned d_reloc : 2; /* Relocatable */
- X unsigned d_rptr : 2; /* Where relocated */
- X short d_lng; /* Length -ve for D_CONT */
- X symbol d_relsymb; /* Relocation symbol */
- X long d_reldisp; /* Offset + or - from symb */
- X symbol d_lab; /* Label */
- X} d_entry;
- X
- X/*
- X * Data types.
- X */
- X
- X#define D_ASC 0 /* Ascii chars */
- X#define D_ASCZ 1 /* Null-term ascii */
- X#define D_BYTE 2 /* Decimal bytes */
- X#define D_WORD 3 /* Words */
- X#define D_LONG 4 /* Longs */
- X#define D_ADDR 5 /* Address pointer */
- X#define D_CONT 6 /* Continuation of last */
- X
- X/*
- X * 'Common' items.
- X */
- X
- Xstruct commit {
- X symbol *c_symb; /* List of symbols */
- X int c_int; /* Current number */
- X int c_max; /* Maximum */
- X};
- X
- X/*
- X * Library file description.
- X */
- X
- Xstruct libit {
- X LDFILE *ldptr,*ldptr2; /* independent file pointer packages
- X for the same file */
- X char lf_name[14]; /* Name of item */
- X};
- X
- X/* magic number stuff like Sun */
- X#define OMAGIC 0407
- X#define NMAGIC 0410
- X#define ZMAGIC 0413
- X#define N_BADMAG(x) \
- X (((x).magic)!=OMAGIC && ((x).magic)!=NMAGIC && ((x).magic)!=ZMAGIC)
- X
- X/* definitions of type for Sun -- used for symstr.type, d_entry.d_rptr */
- X#define S_UNDF 0x0 /* undefined */
- X#define S_ABS 0x2 /* absolute */
- X#define S_TEXT 0x4 /* text */
- X#define S_DATA 0x6 /* data */
- X#define S_BSS 0x8 /* bss */
- X#define S_COMM 0x12 /* common (internal to ld) */
- X#define S_FN 0x1f /* file name symbol */
- X#define S_EXT 01 /* external bit, or'ed in */
- X#define S_TYPE 0x1e /* mask for all the type bits */
- SHAR_EOF
- chmod 0644 unc.h || echo "restore of unc.h fails"
- exit 0
-